package dkim

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"errors"

	"git.oschina.net/chengzishuai/postman/src/net/smtpd/mail"
)

const (
	SignatureHeaderKey  = "DKIM-Signature"
	VersionKey          = "v"
	AlgorithmKey        = "a"
	DomainKey           = "d"
	SelectorKey         = "s"
	CanonicalizationKey = "c"
	QueryMethodKey      = "q"
	BodyLengthKey       = "l"
	TimestampKey        = "t"
	ExpireKey           = "x"
	FieldsKey           = "h"
	BodyHashKey         = "bh"
	SignatureDataKey    = "b"
	AUIDKey             = "i"
	CopiedFieldsKey     = "z"
)

var StdSignableHeaders = []string{
	"Content-Type",
	"Date",
	"From",
	"To",
	"Subject",
}
var StdSignatureTemp = []string{}

//
var privateKey = []byte(
	`-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQC8G4Zto9QmwikmX3ZW8uP1DDM0rPgPJ5Q10VWMeoA8OvMi6gim
7jEGVh4pAGQWc0VlJNCzbqemVqF0GdvE08+1pmlwry0eznDTN6R0yOhPxs6x1jov
adF3VDf/3d+SGBXJGPuN3DP/6GxgXofJuJ6hof5mLHHFPpaKxiP5tdH4TwIDAQAB
AoGBALqOAdASvoCB5xWrb03kLbgFlXMUaB9/fTmylklv5GXXgPKLcHE9oVlLZzX6
sUiioZwh2ulZQONy30SpsI+QEVm7usirJtH3aj73RTeqDx0FIyXf/iGwOd1z+k4k
keHUdNKji8UrKeg/PxdXm9i9FhOlDsyVgCKJR3n1Haow5JMhAkEA9j49ce9vE2GD
hORYds8wy2WGixMrmruKFW00CvWiynZ/U+IGNMsEsUgbVbu3oRUik5EVzuxLgwSQ
apAnBHEWBQJBAMOPlpjjhGly836+OWgs6aaqPYqAoyzkPsTp82uP5v3AKAGCjHae
/btLsZsdhY4o5pGjpVRxm8n+Y81oT5pNcUMCQQDzfxx3nBK0kYriUIMCCWPw3ZYr
1Gsb+TNUeMYryDaQCpliM3F7pv4e6HTPVG8DBMlKLv/nvFX3Wv4Lwjwy8jiZAkAv
WYjhI9VfotGKEozbyGQaUoXsDxFzQSBhlTO3C3SmY+xL0UwpPH2656ztHczEiuqo
wLK7K3bJBasshOEhPzb5AkEAqk1hwAUPPo7fk8pT5XqKZ+uCiWWiFhSCd2hG4RBp
tVNXyXuNEzjLlD0IuRKpZ1EtSl24HoF9Nc73dow6vxQT1Q==
-----END RSA PRIVATE KEY-----`)

//
var publicKey = []byte(`-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8G4Zto9QmwikmX3ZW8uP1DDM0
rPgPJ5Q10VWMeoA8OvMi6gim7jEGVh4pAGQWc0VlJNCzbqemVqF0GdvE08+1pmlw
ry0eznDTN6R0yOhPxs6x1jovadF3VDf/3d+SGBXJGPuN3DP/6GxgXofJuJ6hof5m
LHHFPpaKxiP5tdH4TwIDAQAB
-----END PUBLIC KEY-----`)

//
var signatureTemplate = "v=1; a=rsa-sha256; d=postman.xyz;" +
	" s=515956d5cecd1d211b1629604ad9b61e;c=relaxed/simple; q=dns/txt;" +
	" l=%d; t=%d; h=Date:From:To:Subject:MIME-Version:Content-Type; bh=%s; b="

type Mail struct {
	m mail.Mail
	//私钥
	privateKeyByte []byte
	privateKey     *rsa.PrivateKey
	//公钥
	publicKeyByte []byte
	publicKey     *rsa.PublicKey
	//
	bodyHash            string
	canonicalizedHeader string
	signature           string
}

func New(m mail.Mail) *Mail {
	return &Mail{m: m, privateKeyByte: privateKey, publicKeyByte: publicKey}
}

// 加密
func (m *Mail) GetPrivateKey() error {
	block, _ := pem.Decode(privateKey)
	if block == nil {
		return errors.New("private key error")
	}
	var key *rsa.PrivateKey
	var err error
	key, err = x509.ParsePKCS1PrivateKey(block.Bytes)
	m.privateKey = key
	return err
}
func (m *Mail) getPublicKey() error {
	block, _ := pem.Decode(m.publicKeyByte)
	if block == nil {
		return errors.New("public key error")
	}
	var key interface{}
	var err error
	key, err = x509.ParsePKIXPublicKey(block.Bytes)
	m.publicKey = key.(*rsa.PublicKey)
	return err

}
func (m *Mail) GetBodyHash(body string) error {
	digest := sha256.New()
	digest.Write([]byte(body))
	hashed := digest.Sum(nil)
	m.bodyHash = base64.StdEncoding.EncodeToString(hashed)
	return nil

}
func (m *Mail) GetSignature() error {
	if m.privateKey == nil {
		return errors.New("private key is invalid")
	}
	Canonicalize(m, "relaxed/simple")
	hashed := sha256.Sum256([]byte(m.canonicalizedHeader + m.signature))
	sig, err := rsa.SignPKCS1v15(rand.Reader, m.privateKey, crypto.SHA256, hashed[:])
	if err != nil {
		return err
	}
	m.signature = m.signature + base64.StdEncoding.EncodeToString(sig)
	return nil
}
func (m *Mail) Signature() string {
	return m.signature
}
